#include "gplot.h"

#include <cstdlib>
#include <iostream>
#include <unistd.h>
#include <cstring>

#define GPLOT_EOUT(x) std::cerr << "ERROR [" << __PRETTY_FUNCTION__ << "] " <<  x << "\n"
#define GPLOT_IOUT(x) std::cerr << "INFO  [" << __PRETTY_FUNCTION__ << "] " <<  x << "\n"
#define GP_CMD_SIZE 1024

bool GPlot::init(void)
{
  this->valid = true;
  gplotPipe   = 0;
  
  if (getenv("DISPLAY") == NULL)
    {
      GPLOT_EOUT("Problems on finding DISPLAY variable.");
      this->valid = false;
      return false;
    }
  gplotPipe = popen("gnuplot 2>gnuplot.err","w");
  if (gplotPipe < 0) {
    GPLOT_EOUT("Problems on opening a gnuplot pipe. May be gnuplot is not installed or not in your PATH variable.");
    this->valid = false;
    return false;
  }

  return true;
}

GPlot::GPlot(void)
{
  if (init())
    ;//GPLOT_IOUT("Inited!");
  else
    GPLOT_EOUT("Failed!");
}

GPlot::~GPlot(void)
{
  pclose(gplotPipe);
  //GPLOT_IOUT("Deinited! Bye!");
}

void GPlot::pipeCmdStr(const char* cmdstr, ...)
{
  if (strlen(cmdstr) >= GP_CMD_SIZE)
    {
      GPLOT_EOUT("Failed! Buffer not big enough!");
      return;
    }

  va_list  vlist;
  char     cmd[GP_CMD_SIZE];
  
  va_start(vlist, cmdstr);
  vsprintf(cmd, cmdstr, vlist);
  va_end(vlist);

  strcat(cmd,"\n");
  GPLOT_IOUT("pipe: " << cmd);
  fputs(cmd,gplotPipe);
  fflush(gplotPipe);
  return;
}

void GPlot::pipeCmd(const char* cmdstr)
{
  //GPLOT_IOUT("pipe: " << cmdstr);
  fputs(cmdstr,gplotPipe);
  fflush(gplotPipe);
  return;
}

void GPlot::reset(void)
{
  nplots=0;
}

void GPlot::setLabels(string title, string x, string y)
{
  std::string hs;

  if (title !="")
    hs += "set title \"" + title + "\";";
  if (x!="")
    hs += "set xlabel \"" + x +"\";";
  if (y!="")
    hs += "set ylabel \"" + y +"\";";
  
  pipeCmd(hs.c_str());
}

void GPlot::plot(const std::vector<double> &v, string title, string style, double scale)
{
  char   ch[100];
  string sh;

  if (nplots==0) sh+="plot";
  else sh+="replot";
  sh += " '-' ";
  sh += "title \"" + title;
  if (scale != 1) {
    sprintf(ch, " (scaled: %.3f)", scale);
    sh += ch;
  }
  sh += +"\"";
  if (style!= "") sh += " w " + style;
  sh+="\n";

  for (int i=0; i<(int)v.size(); i++)
    {
      sprintf(ch," %d  %lf\n", i, v[i]*scale); 
      sh= sh + ch;
      if (sh.size() >= GP_CMD_SIZE)
	{
	  pipeCmd(sh.c_str());
	  sh.clear();
	}
    }
  sh += "e\n";
  pipeCmd(sh.c_str());
  nplots++;
}

void GPlot::plot(const std::vector<double> &u, const std::vector<double> &v, string title, string style, double scale)
{  
  char   ch[100];
  string sh;
  
  if (nplots==0) sh+="plot";
  else sh+="replot";
  sh += " '-' ";
  sh += "title \"" + title;
  if (scale != 1) {
    sprintf(ch, " (scaled: %.3f)", scale);
    sh += ch;
  }
  sh += +"\"";
  if (style!= "") sh += " w " + style;
  sh+="\n";
  
  for (int i=0; i<(int)v.size(); i++)
    {
      sprintf(ch," %lf  %lf\n", u[i], v[i]*scale); 
      sh= sh + ch;
      if (sh.size() >= GP_CMD_SIZE)
	{
	  pipeCmd(sh.c_str());
	  sh.clear();
	}
    }
  sh += "e\n";
  pipeCmd(sh.c_str());
  nplots++;
}


void GPlot::plot(string filename, int row2, int row1, int index, string title, string style, double scale2)
{
  char   ch[100];
  string sh;
  
  if (nplots==0) sh+="plot";
  else sh+="replot";
  sh += " \"" + filename + "\"";
  if (index>=0) {
    sprintf(ch, " index %d", index);
    sh+= ch;
  }
  if (scale2 == 1.0)
    sprintf(ch, " u %d:%d", row1, row2);
  else
    sprintf(ch, " u %d:($%d*%f)", row1, row2, scale2);
  sh+=ch;
  if (title!="")
    sh+= " title \"" + title;
  else
    sh+= " title \"" + filename;
  if (scale2 != 1) {
    sprintf(ch, " (scaled: %.3f)", scale2);
    sh += ch;
  }
  sh += +"\"";
  if (style!= "") sh += " w " + style;
  sh+="\n";
  pipeCmd(sh.c_str());
  nplots++;
}

#if 0

int main() {

  vector<double> test;
  GPlot p2;
  p2.setLabels("SimuSys Output 2", "cyclus", "whatever");

  p2.plot("test.log",2,1,"Supertest","lpw",0.001);

  GPlot p;
  p.setLabels("SimuSys Output", "cyclus", "whatever");
  //p.pipeCmdStr("f(x)=x**%.3f; plot f(x)", 2.0);
  p.pipeCmd("plot '-'\n 1.0 1.0\n 2.0 2.0\n 19.0 19.0\n e\n");

 
  sleep(5);

}

#endif
